/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
#include <math.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <string>
#include <vector>
#include <assert.h>
#include "CSDLOpenGLCamera.h"  // Camera handling (move, resize etc)
#include "GLUtils.h"           // Plenty of helpful GL draw functions

///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
/// GLOBALS
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
int Window_ID1;
COpenGLCamera cam;                   // All camera handling
static int done = 0;
static bool finale=false;
///////////////////////////////////////////////////////////////////////////
// Textures
#define TEXTURES_COUNT          1
#define TEXTURE_JARIFACE1       0
#define TEXTURE_JARIFACE1_FILE   "jariface1.png"
static GLuint textures[TEXTURES_COUNT];          // Textures.
static unsigned int draw_interval = 100;
static int previous_floor = -1;
static int previous_floor2 = -2;
///////////////////////////////////////////////////////////////////////////
#define FLOOR1_NUM 111
#define FLOOR2_NUM 222
#define FLOOR3_NUM 333
///////////////////////////////////////////////////////////////////////////
static int lastglerror;
#define GLCHECK() { if ( (lastglerror = glGetError()) != 0) { printf("glGetError at %s:%d yielded %d, '%s'\n", \
                  __FILE__, __LINE__, lastglerror, gluErrorString(lastglerror)); abort(); } }
///////////////////////////////////////////////////////////////////////////

struct trajectoryPoint{
  float x,y,z;
  int color;
		
  trajectoryPoint(){
    set(0,0,0,0);
  }
  trajectoryPoint(float _x,float _y, float _z, int c){x=_x;y=_y;z=_z;color=c;}
  void set(float _x,float _y, float _z, int c){x=_x;y=_y;z=_z;color=c;}	
};

struct line3d{
  float x1,y1,x2,y2,h;
  glutgui::Color col;
  line3d(){
    set(0,0,0,0,0);
  }
  line3d(float _x1,float _y1,float _x2,float _y2,float height){
    x1=_x1;x2=_x2;y1=_y1;y2=_y2;h=height;
  }
  void set(float _x1,float _y1,float _x2,float _y2,float height){
    x1=_x1;x2=_x2;y1=_y1;y2=_y2;h=height;
  }
				
};

static std::vector< trajectoryPoint > trajectory;
static std::vector< line3d > lines;
static int displayListId=-1;
static std::vector<glutgui::Color> colors;


void generateColors(){
  colors.push_back(glutgui::Color(0,1,0));		
  colors.push_back(glutgui::Color(0,0,1));
  colors.push_back(glutgui::Color(0,1,1));
  colors.push_back(glutgui::Color(1,0,0));
  colors.push_back(glutgui::Color(1,1,0));
  colors.push_back(glutgui::Color(1,0,1));
}

bool loadTexture(const char *filename, GLuint textureId)
{
  bool result = true;
  SDL_Surface *surface;
  GLenum texture_format;
  GLint  nOfColors;

  surface = IMG_Load(filename);
  if (surface) {
    // Image format checks
    if ( (surface->w & (surface->w - 1)) != 0 ) {
      printf("warning: Texture width is not a power of 2\n");
    }
    if ( (surface->h & (surface->h - 1)) != 0 ) {
      printf("warning: Texture height is not a power of 2\n");
    }
    
    // get the number of channels in the SDL surface
    nOfColors = surface->format->BytesPerPixel;
    if (nOfColors == 4) {
      // Got ALPHA
      if (surface->format->Rmask == 0x000000ff) {
        texture_format = GL_RGBA; 
        printf("Texture format: GL_RGBA\n");
        
      } else {
        texture_format = GL_BGRA;
        printf("Texture format: GL_BGRA\n");
        
      }
    } else if (nOfColors == 3) {
      // No ALPHA
      if (surface->format->Rmask == 0x000000ff) {
        texture_format = GL_RGB;
        printf("Texture format: GL_RGB\n");

      } else {
        texture_format = GL_BGR;
        printf("Texture format: GL_BGR\n");

      }
    } else {
      printf("Error: the image is not truecolor.\n");
      result = false;

    }

    // Now, if result 
    if (result) {
      // Set the texture's stretching properties
      glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_JARIFACE1]);
      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
      
      // Edit the texture object's image data using the information SDL_Surface gives us
      glTexImage2D( GL_TEXTURE_2D, 0, nOfColors, surface->w, surface->h, 0,
                    texture_format, GL_UNSIGNED_BYTE, surface->pixels );
    } else {
      printf("Invalid image. Cannot use for Texturing.\n");
    }

  } else {
    printf("Failed to load Texture file '%s'! Fatal error, abort!", filename);
    result = false;
    
  }
  
  // Cleanup
  if (surface) {
    SDL_FreeSurface( surface ); 
  }

  return result;
}

void deleteTextures(void)
{
  glDeleteTextures( TEXTURES_COUNT, textures );
}

void loadTextures(void)
{
  // Register cleanup function
  atexit(deleteTextures);

  // Init texture ids
  glGenTextures(TEXTURES_COUNT, textures);

  if (!loadTexture(TEXTURE_JARIFACE1_FILE, textures[TEXTURE_JARIFACE1])) {
    printf("Failed to load JariFace1 texture :( Fatal error\n");
    exit(1);
  }
}


void drawJariTexturedBox(float w, float h, float l, 
                         float x, float y, float z,
                         glutgui::Color c)
{
  glPushMatrix();
  glPushAttrib(GL_ALL_ATTRIB_BITS);

  glDisable(GL_COLOR_MATERIAL);
  glDisable(GL_CULL_FACE);
  glDisable(GL_LIGHTING);
  glDisable(GL_BLEND);

  glEnable(GL_TEXTURE_2D);
  glAlphaFunc(GL_GEQUAL, 0.1);
  glEnable(GL_ALPHA_TEST); 

  //  glColor3f(c.r,c.g,c.b);
  glTranslatef(x, z, -y);
  //glRotatef(90, -1, 0, 0);


  //  glEnable(GL_BLEND);
  //glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); 

  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  glBindTexture( GL_TEXTURE_2D, textures[TEXTURE_JARIFACE1] );
  GLCHECK();

  glBegin(GL_QUADS);
  const float hw = w/2.0;
  const float hh = h/2.0;
  const float hl = l/2.0;

  glNormal3f(0,0,1);

  glTexCoord2i( 0, 0 );
  glVertex3f(hw, hh, hl);

  glTexCoord2i( 1, 0 );
  glVertex3f(-hw, hh, hl);

  glTexCoord2i( 1, 1 );
  glVertex3f(-hw, -hh, hl);

  glTexCoord2i( 0, 1 );
  glVertex3f(hw, -hh, hl);


  glEnd();
  GLCHECK();

  glDisable(GL_TEXTURE_2D);

  glPopAttrib();
  GLCHECK();

  glPopMatrix();
  GLCHECK();
}
/**
* Linemaps
**/
void generateDisplayList(){
  displayListId = glGenLists(1); 
		
  glNewList(displayListId, GL_COMPILE);

  glEnable(GL_COLOR_MATERIAL);
	
  for(int i=0;i<lines.size();i++){
    glutils::drawWall(lines[i].x1, lines[i].y1, lines[i].x2, lines[i].y2, lines[i].h ,0.05, 0.4, lines[i].col);
  }
  glutils::drawGrid(10.0, 100, 0,  colors[0]);
  glEndList();
		
  fprintf(stderr,"Created displayList %d\n",displayListId);
}
static int displayListId2 = 0;

/**
* All trajectory points as boxes
**/
void generateTrajectoryDisplayList(){
  displayListId2 = glGenLists(1); 
		
  glNewList(displayListId2, GL_COMPILE);

  glEnable(GL_COLOR_MATERIAL);
	
  for(int i=1;i<trajectory.size();i++){
      glutils::line3D(trajectory[i-1].x, trajectory[i-1].y, trajectory[i-1].z+0.01, 
                      trajectory[i].x, trajectory[i].y, trajectory[i].z+0.01, colors[trajectory[i].color], 3.0);  	     
			
			glutils::drawBox(0.5, 0.5, 0.5, trajectory[i].x, trajectory[i].y, trajectory[i].z+0.25,
                     colors[trajectory[i].color]);				
  					

    }

  glEndList();
		
  fprintf(stderr,"Created displayList %d\n",displayListId2);
}


int finale_cnt = 0;
void doFinale(){
	if(displayListId2 > 0){
    	if(finale_cnt < 40 ) glCallList(displayListId);
			glCallList(displayListId2);
			
			float a,b,c,d,e;
    	cam.getCameraPose(a,b,c,d,e);
			if(finale_cnt > 100){
					const float yaw = -(180.0/M_PI)*atan2(-c, a) + 90;
					cam.setCameraPose(a-1.0,b-0.2,c+1.0,yaw,20);
			}else{
					cam.setCameraPose(a,b-0.2,c-0.5,0,20);
			}
    	
			finale_cnt++;
  }else{
    generateTrajectoryDisplayList(); 
  }
  
}
/**
 * An example of how to use the 3D visualization stuff. 
 * GLUtils.h
 */
static int num=1;
void do3Doperations(){
  if(finale){
     doFinale();
	   return;
	 }
  //draw_interval = 10;
  //finale = true;
  //fprintf(stderr,"num=%d, trajectory=%d, disp=%d\n ",num,trajectory.size(),displayListId);
  if(displayListId > 0){
    glCallList(displayListId);
				
    for(int i=1;i<num;i++){
      glutils::line3D(trajectory[i-1].x, trajectory[i-1].y, trajectory[i-1].z+0.01, 
                      trajectory[i].x, trajectory[i].y, trajectory[i].z+0.01, colors[trajectory[i].color], 3.0);
						

    }
  //  finale  =true;
   drawJariTexturedBox(1.5, 1.5, 1.5, trajectory[num].x, 
																								trajectory[num].y, trajectory[num].z+(1.5/2),
																								colors[trajectory[num].color]);				
    
    
    //cam.setCameraPose(0, -35,-50, 0, 35); // Some fixed point?
    // cam.setCameraPose(-trajectory[num].x,-trajectory[num].z -3,trajectory[num].y-25, 0, 30);

    //if (num % 40 == 0 || num == 1 || previous_floor != trajectory[num].color) {
    //  previous_floor = trajectory[num].color;
    //  cam.setCameraPose(-trajectory[num].x,-trajectory[num].z -3,trajectory[num].y-15, 0, 30);
   // }
	 
	 
		cam.setCameraPose(-trajectory[num].x,-trajectory[num].z -3,trajectory[num].y-15, 0, 30);
    
		//if(num > 160 && num < 280){
    //  cam.setCameraPose(-trajectory[num-1].x,-trajectory[num-1].z -1,trajectory[num-1].y, 0, 30);
    //  draw_interval = 250;
    //}
		
		if(num>180) draw_interval = 10;
/*
    float a,b,c,d,e;
    cam.getCameraPose(a,b,c,d,e);
    //printf("Camera at %f %f %f\n", a,b,c);
    //printf("Jari at %f %f %f\n", trajectory[num].x, trajectory[num].y, trajectory[num].z);
    const float yaw = -(180.0/M_PI)*atan2(trajectory[num].y-c, trajectory[num].x+a) + 90;
    const float piz = 20;
    cam.setCameraPose(a,b,c,yaw,piz);
  */  
    if(num < trajectory.size()) {
      num++;
    } else {
      finale=true;
      num=1;
    }
    
  }else{
    generateDisplayList();
  }
		
	
  ///
  //glutils::line3D(-10, -10,1, -10, 10, 1 , glutgui::Color(0,1,1));
  //glutils::drawWall(-11, -11, 0, 0, 0.1, 2);
}


/**
 * Called from the render func to draw all the objects
 * 
 */
void drawObjects(){
  static int counter=0;
  counter++;
	
  ///Enable if you want to see amazing 3D :)
  do3Doperations();
	
  assert(glGetError() == GL_NO_ERROR);
}

void drawFloor(int layer)
{
	if(finale) layer=1;
  glColor4f(0.8,0.8,1.0,0.9);
  glBegin(GL_QUADS);
  
  switch(layer) {
  case 1:
    // Bottom floor
    glVertex3f(-100,-.25,100);
    glVertex3f(100,-.25,100);
    glVertex3f(100,-.25,-100);
    glVertex3f(-100,-.25,-100);
    break;
  case 2:
    // 2nd floor
    glVertex3f(-100,4.2,100);
    glVertex3f(100,4.2,100);
    glVertex3f(100,4.2,-100);
    glVertex3f(-100,4.2,-100);
    break;
  case 3:{
    // 3rd floor.
    glVertex3f(-100,7.9,100);
    glVertex3f(100,7.9,100);
    glVertex3f(100,7.9,-100);
    glVertex3f(-100,7.9,-100);
    break;}
  default:
    printf("Unknown floor, stupid!\n");
    abort();
    break;
  }
  glEnd();
}

/**
 * REnder function. Draws everything that is visible.
 */
void renderScene(void) {
  cam.updateCamera();

  float Light_Ambient[]=  { 0.1f, 0.1f, 0.1f, 1.0f };
  float Light_Diffuse[]=  { .6f, .6f, .6f, 1.0f }; 
  float Light_Position[]= { 0.0f, 20.0f, 0.0f, 1.0f };
  float Light_Specular[]= { 5.0f, 5.0f, 5.0f, 10.0f };
	
  float c[4];
  glGetFloatv(GL_CURRENT_COLOR,c);

  glLoadIdentity();
 
  cam.setCamera(); ///< sets up the view
	
  glPushMatrix();
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

  glEnable(GL_LIGHTING);
  glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
  glEnable(GL_COLOR_MATERIAL);
		
  glLightfv(GL_LIGHT1, GL_POSITION, Light_Position);
  glLightfv(GL_LIGHT1, GL_AMBIENT,  Light_Ambient);
  glLightfv(GL_LIGHT1, GL_DIFFUSE,  Light_Diffuse); 
  glLightfv(GL_LIGHT1, GL_SPECULAR,  Light_Specular); 
  glEnable (GL_LIGHT1); 
 
  glEnable(GL_DEPTH_TEST);
  glDepthFunc(GL_LEQUAL);							// The Type Of Depth Testing To Do
  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);			// Really Nice Perspective Calculations		



  //////////////// DRAW OBJECTS ///////////////////
  glPushAttrib(GL_ALL_ATTRIB_BITS);
  glPushMatrix();
  
  drawObjects();
  
  glPopMatrix();
  glPopAttrib();
  
  glPopMatrix();	
  /////////////////////////////////////////////////

  //////////////// Drawing Floors - begin ////////////////
  glPushMatrix();
  glPushAttrib(GL_ALL_ATTRIB_BITS);
  /*  glEnable (GL_BLEND); 
      glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);*/

  drawFloor(1);
  
  //printf("num = %d, Floor %d\n", num, trajectory[num].color);

  switch( trajectory[num].color ) {
  case 0: // 1st floor.
    // drawFloor(2);
    break;

  case 1: // 2nd floor
    drawFloor(2);
    //    drawFloor(3);
    break;

  case 2: // 3rd floor.
    //    drawFloor(2);
    drawFloor(3);
    break;

  case 3: // Stairway (to heaven?)
    if (previous_floor2 == 2) drawFloor(2);
    else if (previous_floor2 == 1) drawFloor(1);
    else if (previous_floor2 == 0) drawFloor(1);
    break;

  default:
    printf("Wtf floor %d?\n", trajectory[num].color);
    abort();
    break;
  }
  
  // If current floor is not stairway, update the previous.
  if (trajectory[num].color != 3 && previous_floor2 != trajectory[num].color) {
    previous_floor2 = trajectory[num].color;
  }

  glDisable (GL_BLEND); 
  glPopAttrib();
  glPopMatrix();
  //////////////// Drawing Floors - end  ////////////////


  glFlush();
  SDL_GL_SwapBuffers();	
}


//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

/**
 * Initializes the example panel
 * Headers:
 * GUIPanel.h
 * Button.h
 * RGBScreen.h
 * RadioButtonGroup.h
 * TextureLabel.h
 **/
void init(){
  glEnable(GL_DEPTH_TEST);
  
  //cam.setCameraPose(0, -8,-20, 0, 25); // Old.
  cam.setCameraPose(0, -35,-50, 0, 35);
  cam.setResolution(0.1, 0.5);
  
  // Load textures.
  loadTextures();

  generateTrajectoryDisplayList();
}

unsigned int getTimeMs(void) 
{
  struct timespec t;
  int r = clock_gettime(CLOCK_MONOTONIC, &t);
  assert(!r);
  unsigned int result = (t.tv_sec * 1000) + (t.tv_nsec/1000000);
  return result;
}

/**
 * Main
 **/
int main(int argc, char* argv[])
{
  SDL_Surface *SDLscreen;
  Uint8 *keys;	
  int videoFlags; ///<Flags to pass to SDL_SetVideoMode
  const SDL_VideoInfo *videoInfo;
  /* whether or not the window is active */
  int isActive = true;
	
  if(argc < 2){
    fprintf(stderr,"----------------------------------------------------------------------------\n");
    fprintf(stderr,"\tPlots linemaps in 3D with 3D trajectory");
    fprintf(stderr,"\tLine maps are given in 2D format with height (file input)\n");
    fprintf(stderr,"\tThe trajectory is given in format [x y z int] where int is an integer [0,1,2] (file input)\n");
    fprintf(stderr,"\tThe integer defines the plot color \n");
    fprintf(stderr,"\n\t\tUsage: ./plot3DmapAndPath [path_file] [mapfile] [mapheight] [mapfile] [mapheight]....\n");
    fprintf(stderr,"\t\t \n");
    fprintf(stderr,"----------------------------------------------------------------------------\n");
    exit(1);
  }
	
  std::string pathfilename=argv[1];
  std::vector< std::string > mapfiles;
  std::vector<float> mapheights;
	
  if(argc>=3){
    for(int i=2;i<argc;i+=2){
      mapfiles.push_back(std::string(argv[i]));
      if(i+1<argc) mapheights.push_back(atof(argv[i+1]));
      else{
        fprintf(stderr,"No mapheight given!!\n");
        exit(1);
      }
    }
  }
  //////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////
  /// READ TRAJECTORY FILE
  //////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////
  FILE *fpath=fopen(pathfilename.c_str(),"rt");
  if(fpath==NULL){
    fprintf(stderr,"Unable to open %s\n",pathfilename.c_str());
    exit(1);
  }
  trajectoryPoint tp;
  while(!feof(fpath)){
    fscanf(fpath,"%f %f %f %d\n",&tp.x,&tp.y,&tp.z,&tp.color);
    trajectory.push_back(tp);
  }
  fclose(fpath);
  //////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////
  generateColors();
  for(int i=0;i<mapfiles.size();i++){
    FILE *fmap = fopen(mapfiles[i].c_str(),"rt");
    line3d l3d;
    l3d.h=mapheights[i];
    srand(time(NULL));
		
    //l3d.col=glutgui::Color(0.2,0.4+ 0.6*(float)(rand()%1000)/1000.0 , 0.4+ 0.6*(float)(rand()%1000)/1000.0 );
    float c = 0.6+ 0.4*(float)(rand()%1000)/1000.0;
		
    //l3d.col=glutgui::Color(c,c , c );
    l3d.col=colors[i];
    l3d.col.r *=0.2;l3d.col.g *=0.2;l3d.col.b *=0.2;
    l3d.col.r +=0.1;l3d.col.g +=0.1;l3d.col.b +=0.1;
    while(!feof(fmap)){
      fscanf(fmap,"%f %f %f %f",&l3d.x1,&l3d.y1,&l3d.x2,&l3d.y2 );
      lines.push_back(l3d);
    }
    fclose(fmap);
  }
	
	
	
	
	
  SDL_Init(SDL_INIT_VIDEO);
  if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ){
    fprintf( stderr, "Video initialization failed: %s\n",SDL_GetError( ) );
    exit(1);
  }

  /* Fetch the video info */
  videoInfo = SDL_GetVideoInfo( );

  if ( !videoInfo ){
    fprintf( stderr, "Video query failed: %s\n", SDL_GetError( ) );
    exit( 1 );
  }

  /* the flags to pass to SDL_SetVideoMode */
  videoFlags  = SDL_OPENGL;          /* Enable OpenGL in SDL */
  videoFlags |= SDL_GL_DOUBLEBUFFER; /* Enable double buffering */
  videoFlags |= SDL_HWPALETTE;       /* Store the palette in hardware */
  videoFlags |= SDL_RESIZABLE;       /* Enable window resizing */

  /* This checks to see if surfaces can be stored in memory */
  if ( videoInfo->hw_available ) videoFlags |= SDL_HWSURFACE;
  else videoFlags |= SDL_SWSURFACE;

  /* This checks if hardware blits can be done */
  if ( videoInfo->blit_hw ) videoFlags |= SDL_HWACCEL;
  SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

  /* get a SDL surface */
  SDLscreen = SDL_SetVideoMode( 800,600, 24, videoFlags);

  /* Verify there is a surface */
  if ( !SDLscreen ){
    fprintf( stderr,  "Video mode set failed: %s\n", SDL_GetError( ) );
    exit( 1 );
  }
	
  SDL_WM_SetCaption("3D-IMU Walk with topoMCL result", "3D-IMU Walk with topoMCL result");

  init();
  cam.resizeFunc(SDLscreen->w, SDLscreen->h);
  done = 0;
  unsigned int lastdraw = 0;

  // Sleep 10sec before start.
  //usleep(10 * 1000 * 1000);

  while ( ! done ) {
    SDL_Event event;
    while ( SDL_PollEvent(&event) ) {
      switch(event.type) {
      case SDL_ACTIVEEVENT:
        //if ( event.active.gain == 0 ) isActive = false;
        //else isActive = true;
        break;
      case SDL_VIDEORESIZE:
        SDLscreen = SDL_SetVideoMode(event.resize.w, event.resize.h, 32,
                                     SDL_OPENGL|SDL_RESIZABLE);
        if ( SDLscreen ) {
          cam.resizeFunc(SDLscreen->w, SDLscreen->h);
        } else {
          /* Uh oh, we couldn't set the new video mode?? */;
        }
        break;
      case SDL_QUIT: done = 1;break;
      case SDL_KEYDOWN:
      case SDL_KEYUP:
        cam.cameraKeyFunc(event.key); ///<Camera handling
        break;
      case SDL_MOUSEBUTTONDOWN:
        if(event.button.button == SDL_BUTTON_LEFT)
          break;     
      case SDL_MOUSEBUTTONUP: 
        break;
      case SDL_MOUSEMOTION:
        break;
      case SDL_JOYAXISMOTION:	break;
      case SDL_JOYBALLMOTION: break;
      case SDL_JOYHATMOTION: break;
      case SDL_JOYBUTTONDOWN: break;
      case SDL_JOYBUTTONUP: break;
					
      }
    }
    keys = SDL_GetKeyState(NULL);

    if ( keys[SDLK_ESCAPE] ) {
      done = 1;
    }
    if(keys[SDLK_F1]){ ///Bring panel to camera
    }

    if(isActive && getTimeMs() - lastdraw > draw_interval) {
      lastdraw = getTimeMs();
      renderScene();
    } else {
      usleep(5000);
   
    }

  }

  SDL_Quit();
  return 0;
}


